home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
workbench erweiterungen
/
avwm-0.4
/
avwm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
19KB
|
773 lines
/*
avwm 0.4 / Amiga Virtual Workbench Manager
5/2/93 Bernhard Fastenrath
Public Domain
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <dos.h>
#include <exec/types.h>
#include <devices/timer.h>
#include <graphics/rastport.h>
#include <intuition/intuitionbase.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include "callbacks.h"
#include "avwm.h"
#include "wbwm.h"
const char *Version = VERSION;
struct IntuitionBase *IntuitionBase = NULL;
struct timerequest *TimerIO = NULL;
struct MsgPort *TimerPort = NULL;
struct Window *Win = NULL,
*LastActiveWindow = NULL;
struct RastPort *Rp;
short Screenwidth, Screenheight,
VisWidth, VisHeight;
struct List VWinA[2];
int Options = OPT_NO_SETF | OPT_MOVE_SCREEN,
VWIndex = 0, Dx, Dy,
Action = ACT_NONE, Area = 0,
Seconds = 2, MSeconds = 0;
Offset = 11;
ULONG WMSigBit = -1, WMSig;
struct vWindow *Cvw = NULL;
char *PubScreenName = "Workbench";
int
main (int argc, char *argv[])
{
struct Screen *Lock;
struct NewWindow NewWin;
int argn = 1;
char optc;
while (argn < argc)
if (argopt (argc, argv, "OcS", &argn, &optc))
switch (optc) {
case 'O':
Offset = atoi (argv[argn-1] + (argv[argn-1][0] == '-' ? 2 : 0));
break;
case 'h':
printf ("Amiga Virtual Workbench Manager %d.%d\n", VER_NUM, REV_NUM);
printf ("Options: -t don't open timer device.\n");
printf (" -c <n> check windows every n seconds (default: 2s).\n");
printf (" -s use SetFunction () (by default disabled now).\n");
printf (" -m use MoveWindow (expects double v. screen size) instead of\n");
printf (" MoveScreen (expects triple h. and double v. screen size).\n");
printf (" -S Name of public screen (default: Workbench).\n");
exit (0);
case 'c':
Seconds = atoi (argv[argn-1] + (argv[argn-1][0] == '-' ? 2 : 0));
if (Seconds == 0) MSeconds = 250;
break;
case 't':
Options |= OPT_NO_TIMER;
break;
case 's':
Options &= ~OPT_NO_SETF;
break;
case 'm':
Options &= ~OPT_MOVE_SCREEN;
break;
case 'S':
PubScreenName = argv[argn-1] + (argv[argn-1][0] == '-' ? 2 : 0);
break;
default:
printf ("Invalid Option: \"-%c\" (try '%s -h')\n", optc, argv[0]);
exit (20);
}
else
argn++;
InitListHeader ((struct MinList *) &VWinA[0]);
InitListHeader ((struct MinList *) &VWinA[1]);
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37L))) {
printf ("%s: Can't open intuition library 37.x.\n", Version);
exit_avwm (1);
}
if ((Lock = LockPubScreen (PubScreenName)) == NULL) {
printf ("%s: Can't lock public screen '%s'.\n", Version, PubScreenName);
exit_avwm (1);
}
Screenwidth = Lock -> Width;
Screenheight = Lock -> Height;
if (Options & OPT_MOVE_SCREEN) {
VisWidth = Screenwidth / 3;
VisHeight = Screenheight / 2;
}
else {
VisWidth = Screenwidth;
VisHeight = Screenheight / 2;
}
NewWin.LeftEdge = VisWidth - AVWM_WIDTH;
NewWin.TopEdge = 12;
NewWin.Width = AVWM_WIDTH;
NewWin.Height = AVWM_HEIGHT;
NewWin.DetailPen = 0;
NewWin.BlockPen = 1;
NewWin.Title = "Virtual Desktop";
NewWin.Flags = WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH |
GIMMEZEROZERO | ACTIVATE | RMBTRAP | REPORTMOUSE;
NewWin.IDCMPFlags = MOUSEBUTTONS | CLOSEWINDOW | REFRESHWINDOW | MOUSEMOVE;
NewWin.Type = PUBLICSCREEN;
NewWin.FirstGadget = NULL;
NewWin.CheckMark = NULL;
NewWin.Screen = Lock;
NewWin.BitMap = NULL;
NewWin.MinWidth = 0;
NewWin.MinHeight = 0;
NewWin.MaxWidth = 0;
NewWin.MaxHeight = 0;
if (!(Win = OpenWindow (&NewWin))) {
UnlockPubScreen (NULL, Lock);
printf ("%s: Can't open window.\n", Version);
exit_avwm (20);
}
UnlockPubScreen (NULL, Lock);
Rp = Win -> RPort;
AddCallback (Win, close_window, CLOSEWINDOW);
AddCallback (Win, mouse_event, MOUSEBUTTONS);
AddCallback (Win, refresh_window, REFRESHWINDOW);
AddCallback (Win, mouse_move, MOUSEMOVE);
if ((Options & OPT_NO_TIMER) == 0)
{
init_timer ();
AddPortCallback (TimerPort, (callback) timer_event, 0);
}
if ((Options & OPT_NO_SETF) == 0)
{
if ((WMSigBit = AllocSignal (-1)) == -1)
{
printf ("%s: Can't allocate Signal.\n", Version);
exit_avwm (20);
}
start_window_monitor ();
WMSig = 1L << WMSigBit;
SetSignalCallback (WMSig, (callback) workbench_monitor_event);
}
refresh_graphic ();
AppMainLoop ();
exit_avwm (0);
}
void
exit_avwm (int code)
{
struct Node *node;
stop_window_monitor ();
while (node = RemTail (&VWinA[0]))
free (node);
while (node = RemTail (&VWinA[1]))
free (node);
if (WMSigBit != -1) FreeSignal (WMSigBit);
if (Win) CloseWindow (Win);
if ((Options & OPT_NO_SETF) == 0) Delay (100);
if (TimerIO) {
AbortIO ((struct IORequest *) TimerIO);
WaitIO ((struct IORequest *) TimerIO);
CloseDevice ((struct IORequest *) TimerIO);
DeleteExtIO ((struct IORequest *) TimerIO, sizeof (struct timerequest));
}
if (TimerPort) DeletePort (TimerPort);
RemoveAllCallbacks ();
if (IntuitionBase) CloseLibrary ((struct Library *) IntuitionBase);
exit (code);
}
void
init_timer ()
{
int err;
if (!(TimerPort = CreatePort (0, 0)))
{
printf ("%s: Can't create message port.\n", Version);
exit_avwm (1);
}
if (!(TimerIO = (struct timerequest *) CreateExtIO (TimerPort, sizeof (struct timerequest))))
{
printf ("%s: Out of memory.\n", Version);
exit_avwm (1);
}
if (err = OpenDevice (TIMERNAME, UNIT_VBLANK, (struct IORequest *) TimerIO, 0))
{
printf ("%s: Can't open timer.device (code %d).\n", Version, err);
exit_avwm (1);
}
TimerIO -> tr_time.tv_secs = Seconds;
TimerIO -> tr_time.tv_micro = MSeconds;
TimerIO -> tr_node.io_Command = TR_ADDREQUEST;
SendIO ((struct IORequest *) TimerIO);
}
struct Window *
assert_window (struct Window *search)
{
struct Window *window;
for (window = Win -> WScreen -> FirstWindow; window; window = window -> NextWindow)
if (search == window) return window;
return NULL;
}
void
draw_box (short color, short x1, short y1, short x2, short y2, struct RastPort *rp)
{
SetAPen (rp, GREY);
RectFill (rp, x1, y1, x2, y2);
SetAPen (rp, color);
Move (rp, x1, y1);
Draw (rp, x2, y1);
Draw (rp, x2, y2);
Draw (rp, x1, y2);
Draw (rp, x1, y1);
}
void
draw_frame (short color, short x1, short y1, short x2, short y2, struct RastPort *rp)
{
SetAPen (rp, color);
Move (rp, x1, y1);
Draw (rp, x2, y1);
Draw (rp, x2, y2);
Draw (rp, x1, y2);
Draw (rp, x1, y1);
}
void
draw_vwindow (int color, struct vWindow *vw)
{
int x, y;
x = vw -> sx + AREA_X (vw -> area) * SUB_WIDTH;
y = vw -> sy + AREA_Y (vw -> area) * SUB_HEIGHT;
draw_frame (color, x, y, x + vw -> sw, y + vw -> sh, Rp);
}
void
redraw_graphic ()
{
struct vWindow *vw;
struct List *vwl;
short color;
int x, y;
vwl = &VWinA[VWIndex];
SetDrMd (Rp, JAM2);
SetAPen (Rp, GREY);
RectFill (Rp, 0, 0, AVWM_WIDTH, AVWM_HEIGHT);
SetAPen (Rp, BLACK);
Move (Rp, 0, SUB_HEIGHT); Draw (Rp, SUB_WIDTH * 3, SUB_HEIGHT);
Move (Rp, SUB_WIDTH, 0); Draw (Rp, SUB_WIDTH, SUB_HEIGHT * 2);
Move (Rp, SUB_WIDTH * 2, 0); Draw (Rp, SUB_WIDTH * 2, SUB_HEIGHT * 2);
for (vw = (struct vWindow *) vwl -> lh_TailPred;
vw -> node.ln_Pred; vw = (struct vWindow *) vw -> node.ln_Pred)
{
if (IntuitionBase -> ActiveWindow == vw -> window)
color = BLUE;
else
color = BLACK;
x = vw -> sx + AREA_X (vw -> area) * SUB_WIDTH;
y = vw -> sy + AREA_Y (vw -> area) * SUB_HEIGHT;
draw_box (color, x, y, x + vw -> sw, y + vw -> sh, Rp);
}
}
void
refresh_graphic ()
{
struct Window *window;
struct vWindow *vw;
short change = 0;
BYTE pos;
struct List *vwl, *vwl2;
struct Layer *layer;
int area;
Forbid ();
if (IntuitionBase -> FirstScreen != Win -> WScreen
&& IntuitionBase -> ActiveScreen != Win -> WScreen)
{
Permit ();
return; /* Screen not in use, event ignored */
}
vwl = &VWinA[VWIndex];
VWIndex = 1 - VWIndex;
vwl2 = &VWinA[VWIndex];
if (LastActiveWindow != IntuitionBase -> ActiveWindow)
{
LastActiveWindow = IntuitionBase -> ActiveWindow;
change = 1;
}
/* Set the change status of all windows to "unknown" */
for (vw = (struct vWindow *) vwl -> lh_Head;
vw -> node.ln_Succ; vw = (struct vWindow *) vw -> node.ln_Succ)
{
vw -> changed = -1;
}
/* Find the front layer */
for (layer = Win -> WScreen -> FirstWindow -> WLayer;
layer -> front; layer = layer -> front);
/* Sort the virtual window list like the layers of the screen
and check if size, position or priority of any window changed
*/
for (pos = HIGH_PRI; layer -> back; pos--, layer = layer -> back)
{
if (!(window = layer -> Window)) continue;
for (vw = (struct vWindow *) vwl -> lh_Head;
vw -> node.ln_Succ; vw = (struct vWindow *) vw -> node.ln_Succ)
{
if (vw -> window == window)
{
if (vw -> changed != -1) break;
vw -> changed = 0; /* Window has moved? */
if (vw -> ox != window -> LeftEdge)
{ vw -> ox = window -> LeftEdge; change = vw -> changed = 1; }
if (vw -> oy != window -> TopEdge)
{ vw -> oy = window -> TopEdge; change = vw -> changed = 1; }
if (vw -> ow != window -> Width)
{ vw -> ow = window -> Width; change = vw -> changed = 1; }
if (vw -> oh != window -> Height)
{ vw -> oh = window -> Height; change = vw -> changed = 1; }
if (vw -> changed)
{
/* Window has moved into another area? */
area = AREA (window -> LeftEdge, window -> TopEdge);
/* Don't change the area if MoveWindow is used
and the window is invisible
because it will always be found in the lower
"invisible" part of the screen
*/
if (Options & OPT_MOVE_SCREEN)
vw -> area = area;
else if (area == 0)
vw -> area = Area;
#ifdef DEBUG
printf ("Window %d moved to %d,%d in area %d.\n", vw -> window, vw -> ox, vw -> oy, area);
#endif
}
if (vw -> node.ln_Pri != pos) /* Window order has changed */
{
#ifdef DEBUG
printf ("Window order has changed. (area %d) [was: %d, is: %d]\n", vw->area, vw->node.ln_Pri, pos);
#endif
vw -> node.ln_Pri = pos;
change = 1;
}
break;
}
}
if (!vw -> node.ln_Succ) /* New window has been opened */
{
if (!(vw = Malloc (struct vWindow))) {
Permit ();
printf ("%s: Memory low!.\n", Version);
exit_avwm (1);
}
vw -> area = AREA (window -> LeftEdge, window -> TopEdge);
/* Set the area to the area currently displayed in area 0 */
if (!(Options & OPT_MOVE_SCREEN) && vw -> area == 0)
vw -> area = Area;
#ifdef DEBUG
printf ("Adding window to area %d.\n", vw -> area);
#endif
vw -> changed = 2;
vw -> window = window;
vw -> node.ln_Pri = pos;
vw -> ox = window -> LeftEdge;
vw -> oy = window -> TopEdge;
vw -> ow = window -> Width;
vw -> oh = window -> Height;
AddHead (vwl, (struct Node *) vw);
change = 1;
}
}
Permit ();
while (vw = (struct vWindow *) RemTail (vwl))
{
if (vw -> changed == -1) { /* Window has been closed */
free (vw);
change = 1;
#ifdef DEBUG
printf ("Window removed.\n");
#endif
}
else /* If the window order is unchanged this is just an AddHead() */
Enqueue (vwl2, (struct Node *) vw);
}
if (change) /* Don't draw if nothing has happened */
{
if (Options & OPT_MOVE_SCREEN)
for (vw = (struct vWindow *) vwl2 -> lh_TailPred;
vw -> node.ln_Pred; vw = (struct vWindow *) vw -> node.ln_Pred)
{
vw -> sx = (vw -> ox % VisWidth) * SUB_WIDTH / VisWidth;
vw -> sy = (vw -> oy % VisHeight) * SUB_HEIGHT / VisHeight;
vw -> sw = vw -> ow * SUB_WIDTH / VisWidth;
vw -> sh = vw -> oh * SUB_HEIGHT / VisHeight;
}
else
for (vw = (struct vWindow *) vwl2 -> lh_TailPred;
vw -> node.ln_Pred; vw = (struct vWindow *) vw -> node.ln_Pred)
{
/* ignore window's position (but not size)
if it is invisible
*/
if (vw -> area == Area || vw -> changed == 2)
{
vw -> sx = (vw -> ox % VisWidth) * SUB_WIDTH / VisWidth;
vw -> sy = (vw -> oy % VisHeight) * SUB_HEIGHT / VisHeight;
}
vw -> sw = vw -> ow * SUB_WIDTH / VisWidth;
vw -> sh = vw -> oh * SUB_HEIGHT / VisHeight;
}
redraw_graphic ();
}
}
struct vWindow *
find_window (int x, int y)
{
struct vWindow *vw;
struct List *vwl;
int area;
vwl = &VWinA[VWIndex];
area = vAREA (x, y); x %= SUB_WIDTH; y %= SUB_HEIGHT;
for (vw = (struct vWindow *) vwl -> lh_Head;
vw -> node.ln_Succ; vw = (struct vWindow *) vw -> node.ln_Succ)
{
if (x > vw->sx && y > vw->sy && x < vw->sw + vw->sx && y < vw->sh + vw->sy
&& area == vw -> area)
return vw;
}
return NULL;
}
int
close_window (struct IntuiMessage *msg, struct Callback *cb)
{
exit_avwm (0);
return 0;
}
int
refresh_window (struct IntuiMessage *msg, struct Callback *cb)
{
return 0;
}
int
timer_event (struct timerequest *msg, struct Callback *cb)
{
TimerIO -> tr_time.tv_secs = Seconds;
TimerIO -> tr_time.tv_micro = MSeconds;
TimerIO -> tr_node.io_Command = TR_ADDREQUEST;
SendIO ((struct IORequest *) TimerIO);
if (!Action) refresh_graphic ();
return 0;
}
void
workbench_monitor_event (int signals)
{
#ifdef xDEBUG
printf ("Monitor Event (signal: %d).\n", signals);
#endif
if (!Action) refresh_graphic ();
#ifdef xDEBUG
else printf ("Monitor Event ignored.\n");
#endif
}
int
mouse_move (struct IntuiMessage *msg, struct Callback *cb)
{
if (Action == ACT_NONE) return 0;
if (Action == ACT_MOVE_WIN)
{
draw_vwindow (WHITE, Cvw);
Cvw -> sx += msg -> MouseX - Dx;
Cvw -> sy += msg -> MouseY - Dy;
Dx = msg -> MouseX;
Dy = msg -> MouseY;
draw_vwindow (WHITE, Cvw);
}
return 0;
}
static void
change_area (int x, int y)
{
struct vWindow *vw;
WORD dx, dy;
short oldarea;
oldarea = Area;
Area = vAREA (x, y);
if (oldarea == Area)
return;
#ifdef xDEBUG
printf ("Visible area was %d, now %d.\n", oldarea, Area);
#endif
if (Options & OPT_MOVE_SCREEN)
{
dx = VisWidth * AREA_X (Area) + Win -> WScreen -> LeftEdge;
dy = VisHeight * AREA_Y (Area) + Win -> WScreen -> TopEdge;
MoveScreen (Win -> WScreen, -dx, -dy);
MoveWindow (Win, dx, dy);
}
else
{
for (vw = (struct vWindow *) VWinA[VWIndex].lh_Head;
vw -> node.ln_Succ; vw = (struct vWindow *) vw -> node.ln_Succ)
{
if (vw -> window == Win) /* The awvm window always stays */
{
vw -> area = Area;
}
else if (vw -> area == oldarea)
{
Forbid ();
if (assert_window (vw -> window)) /* Move it away */
{
ChangeWindowBox (vw -> window,
0, VisHeight,
vw -> window -> Width,
vw -> window -> Height);
}
Permit ();
}
#if 0 /* Remove, then add windows -- this looks better and is probably faster */
else if (vw -> area == Area)
#else
}
for (vw = (struct vWindow *) VWinA[VWIndex].lh_Head;
vw -> node.ln_Succ; vw = (struct vWindow *) vw -> node.ln_Succ)
{
if (vw -> area == Area && vw -> window != Win)
#endif
{
Forbid ();
if (assert_window (vw -> window)) /* Make it visible */
{
ChangeWindowBox (vw -> window,
vw -> sx * VisWidth / SUB_WIDTH + Offset,
vw -> sy * VisHeight / SUB_HEIGHT + Offset,
vw -> window -> Width,
vw -> window -> Height);
}
Permit ();
}
}
}
}
int
mouse_event (struct IntuiMessage *msg, struct Callback *cb)
{
static ULONG lsecs = 0, lmicros = 0;
static int start_x, start_y;
ULONG secs = 0, micros = 0;
int x, y;
x = Win -> GZZMouseX;
y = Win -> GZZMouseY;
switch (msg -> Code)
{
case SELECTDOWN:
CurrentTime (&secs, µs);
if (DoubleClick (lsecs, lmicros, secs, micros))
{
lsecs = lmicros = 0;
change_area (x, y);
}
else
{
if (Cvw = find_window (x, y))
{
Action = ACT_MOVE_WIN;
SetDrMd (Rp, COMPLEMENT);
draw_vwindow (WHITE, Cvw); /* Create temporary image */
Dx = msg -> MouseX;
Dy = msg -> MouseY;
start_x = Cvw -> sx;
start_y = Cvw -> sy;
}
lsecs = secs;
lmicros = micros;
}
break;
case SELECTUP:
if (Cvw)
{
int area;
Action = ACT_NONE;
draw_vwindow (WHITE, Cvw); /* Remove temporary image */
SetDrMd (Rp, JAM2);
area = vAREA (x, y);
while (Cvw -> sx < 0) Cvw -> sx += SUB_WIDTH;
while (Cvw -> sy < 0) Cvw -> sy += SUB_HEIGHT;
Cvw -> sx %= SUB_WIDTH;
Cvw -> sy %= SUB_HEIGHT;
if ((start_x + 1 > Cvw -> sx && start_x - 1 < Cvw -> sx &&
start_y + 1 > Cvw -> sy && start_y - 1 < Cvw -> sy &&
area == Cvw -> area) ||
(area != Cvw -> area && Cvw -> window == Win))
{
Cvw = NULL;
break;
}
Forbid ();
if (assert_window (Cvw -> window))
{
struct Window *win;
win = Cvw -> window;
if (area == Area) /* Destination area is visible */
{
if (Options & OPT_MOVE_SCREEN) {
ChangeWindowBox (Cvw -> window,
Cvw -> sx * VisWidth / SUB_WIDTH + AREA_X (area) * VisWidth,
Cvw -> sy * VisHeight / SUB_HEIGHT + AREA_Y (area) * VisHeight,
win -> Width, win -> Height);
}
else {
ChangeWindowBox (Cvw -> window,
Cvw -> sx * VisWidth / SUB_WIDTH,
Cvw -> sy * VisHeight / SUB_HEIGHT,
win -> Width, win -> Height);
}
}
else
{
if (Options & OPT_MOVE_SCREEN) { /* Six areas (3 * 2) */
ChangeWindowBox (Cvw -> window,
Cvw -> sx * VisWidth / SUB_WIDTH + AREA_X (area) * VisWidth,
Cvw -> sy * VisHeight / SUB_HEIGHT + AREA_Y (area) * VisHeight,
win -> Width, win -> Height);
}
else { /* Two `real' areas (1 * 2) */
ChangeWindowBox (Cvw -> window,
0, VisHeight, win -> Width, win -> Height);
}
}
Permit ();
Cvw -> area = area;
}
else {
Permit ();
DisplayBeep (Win -> WScreen);
}
Cvw = NULL;
redraw_graphic ();
}
break;
case MIDDLEDOWN: break;
case MIDDLEUP:
change_area (x, y);
break;
case MENUDOWN: break;
case MENUUP:
if (Cvw) break;
if (Cvw = find_window (x, y))
{
Forbid ();
if (assert_window (Cvw -> window))
{
ZipWindow (Cvw -> window);
}
Permit ();
Cvw = NULL;
}
break;
default: break;
}
return 0;
}
/* Shouldn't this disable SAS/C's ctrl-c handling? */
void CXBRK () {}
void chkabort () {}